package com.otherTest.java8.groupingBy;


import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.otherTest.java8.CollectorsUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.junit.Test;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.Month;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: 测试groupingBy分组
 * @author: conceit
 * @Date: 2018/10/9  14:01
 */
public class TestGroupingBy {

    //分组取出男性和女性的个数以 map的形式
    //{MALE=4, FEMALE=2}
    @Test
    public void test1() {

        System.out.println(persons().stream().collect(Collectors.groupingBy(Employee::getGender, Collectors.counting())));
    }

    //以男性和女性为key,value 对应为成员数组
    //{male=[],female=[]}
    //.entrySet() 是以set集合的形式返回流对象。Set<Map.Entry<K, V>>
    @Test
    public void test2() {
        Object groupingBy = persons().stream().collect(Collectors.groupingBy(Employee::getGender)).entrySet();
        System.out.println(groupingBy);
    }

    //求姓名一样的成员，工资总和
    @Test
    public void test3() {
            Map<String, Double> personMap = persons().stream().collect(Collectors.groupingBy(Employee::getName, Collectors.summingDouble(Employee::getIncome)));
        System.out.println(personMap);
    }

    //对bigDig 进行求和
    @Test
    public void test4() {
        Map<String, BigDecimal> personMap = persons().stream().collect(Collectors.groupingBy(Employee::getName, CollectorsUtil.summingBigDecimal(Employee::getAmount)));
        System.out.println(personMap);
    }

    //日期格式化后 进行同一时间分组，并对bigDecimal求和
    @Test
    public void test5() {
        System.out.println(humanList().stream().collect(Collectors.groupingBy(Human::getCreateDate, CollectorsUtil.summingBigDecimal(Human::getAmount))));
        Map<Date, BigDecimal> result = humanList().stream().collect(Collectors.groupingBy(Human::getCreateDate, CollectorsUtil.summingBigDecimal(Human::getAmount)));

    }

    @Test
    public void test6() {
        System.out.println(humanList().stream().collect(Collectors.groupingBy(Human::getCreateDate, CollectorsUtil.summingBigDecimal(Human::getAmount))));
    }
    /**
     * 用男女性别 作为key
     *
     */
    @Test
    public void test7(){
        Map map=persons().stream().collect(Collectors.groupingBy(Employee::getGender));
        System.out.print(map);
    }

    /**
     * 通过参数mapper函数来处理List中的每一个数据，然后用downstream来将处理后的数据收集起来
     * 男性的所有人员分为一组 性别作为key 姓名作为value list
     */
    @Test
    public void test8(){
        Map map=persons().stream().collect(Collectors.groupingBy(Employee::getGender,Collectors.mapping(Employee::getName,Collectors.toList())));
        System.out.print(JSON.toJSONString(map));
    }

    /**
     *
     */
    @Test
    public void test9(){
        //System.out.print(JSON.toJSONString(persons()));

        TreeMap<String,Employee> treeMap=persons().stream().collect(TreeMap::new,(k,v)->{
            System.out.println("before k -->"+k);
            System.out.println("before v -->"+v);

            k.put(v.name,v);
            if(CollUtil.isNotEmpty(k)){
                System.out.println("lastkey k -->"+k.lastKey());
            }
            System.out.println("after k -->"+k);
            System.out.println("after k -->"+v);
            System.out.println("------------------------------------------------");
        },TreeMap::putAll);
        System.out.println("/////////////////////////////////////////////////////////////////");
       System.out.println(JSON.toJSONString(treeMap));
       System.out.println(treeMap.lastKey());
        //persons().stream().collect();
    }

    /**
     * 生成不大于lastKey的随机数
     * 取出大于它的全部视图
     * 并取出第一个对象
     *
     * 注意因为TreeMap是有序的，key有重复会覆盖
     */
    @Test
    public void test10(){
        Double lastKey=1D;
        TreeMap<Double,String> treeMap=new TreeMap<>();
        treeMap.put(0.1,"zhaohang");
        treeMap.put(0.2,"zhaohang");
        treeMap.put(0.3,"zhaohang");
        treeMap.put(0.4,"zhaohang");
        treeMap.put(0.5,"zhaohang");
        treeMap.put(lastKey,"zhaohang");

        double random= ThreadLocalRandom.current().nextDouble(lastKey);
        System.out.println("random"+random);

        System.out.println();

        SortedMap<Double,String> sortedMap=treeMap.tailMap(random,false);
        System.out.println("tailMap-->"+sortedMap);

    }


    @Test
    public void test11(){
        Map<String,String> map=new HashMap<>();
        map.put(new Integer(1).toString(),"1");
        map.put(new Integer(2).toString(),"2");
        System.out.print(JSON.toJSONString(map));
    }

    public List<Human> humanList() {
        Human id1 = new Human(1, new Date(), "zhaohang", new BigDecimal("50"));

        Human id2 = new Human(2, new Date(1539151748000L), "zhaoJIE", BigDecimal.TEN);
        Human id3 = new Human(3, new Date(1539151748000L), "zhaodi", new BigDecimal("100"));

        Human id4 = new Human(4, new Date(1541862548000L), "zhaodi", new BigDecimal("1000"));

        List<Human> humanList = new ArrayList<>();
        humanList.add(id1);
        humanList.add(id2);
        humanList.add(id3);
        humanList.add(id4);
        return humanList;
    }

    public List<TestGroupingBy.Employee> persons() {
        TestGroupingBy.Employee p1 = new TestGroupingBy.Employee(1, "Jake", TestGroupingBy.Employee.Gender.MALE, LocalDate.of(1972,
                Month.JANUARY, 1), 2343.0, new BigDecimal(10));
        TestGroupingBy.Employee p2 = new TestGroupingBy.Employee(2, "Jake", TestGroupingBy.Employee.Gender.MALE, LocalDate.of(1972,
                Month.JULY, 21), 7100.0, new BigDecimal(9));
        TestGroupingBy.Employee p3 = new TestGroupingBy.Employee(3, "Jane", TestGroupingBy.Employee.Gender.FEMALE, LocalDate.of(1973,
                Month.MAY, 29), 5455.0, new BigDecimal(99));
        TestGroupingBy.Employee p4 = new TestGroupingBy.Employee(4, "Jode", TestGroupingBy.Employee.Gender.MALE, LocalDate.of(1974,
                Month.OCTOBER, 16), 1800.0, new BigDecimal(8.888));
        TestGroupingBy.Employee p5 = new TestGroupingBy.Employee(5, "Jeny", TestGroupingBy.Employee.Gender.FEMALE, LocalDate.of(1975,
                Month.DECEMBER, 13), 1234.0, new BigDecimal(13.33));
        TestGroupingBy.Employee p6 = new TestGroupingBy.Employee(6, "Jason", TestGroupingBy.Employee.Gender.MALE, LocalDate.of(1976,
                Month.JUNE, 9), 3211.0, new BigDecimal(11.11));

        List<TestGroupingBy.Employee> persons = Arrays.asList(p1, p2, p3, p4, p5, p6);

        return persons;
    }

    @Data
    @AllArgsConstructor
    public static class Human {
        private long id;
        private Date createDate;
        private String name;
        private BigDecimal amount;
    }

    @Data
    static class Employee {

        public enum Gender {
            MALE, FEMALE
        }


        private long id;
        private String name;
        private TestGroupingBy.Employee.Gender gender;
        private LocalDate dob;
        private double income;
        private BigDecimal amount;

        public Employee(long id, String name, TestGroupingBy.Employee.Gender gender, LocalDate dob,
                        double income, BigDecimal amount) {
            this.id = id;
            this.name = name;
            this.gender = gender;
            this.dob = dob;
            this.income = income;
            this.amount = amount;
        }

        public long getId() {
            return id;
        }

        public String getName() {
            return name;
        }


    }
}
